import { BaseHttpService } from "../../../shared/services/baseHttp.service";
import { HttpClient, HttpParams } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable, ReplaySubject, Subscription } from "rxjs";
import { StorageService } from "../../../shared/services/storage.service";
import { Subject } from "rxjs/Subject";
import { BehaviorSubject } from "rxjs/BehaviorSubject";
import { CompanyModel } from "./company.model";
import { Routes, Route } from "@angular/router";
import { CompanyHeaderModel } from "./shared/companyHeader/companyHeader.model";
import { RouteGuard } from "../../../guards/route.guard";
import { CompanyReportDownloadModel } from "./shared/companyHeader/companyReportDownload/companyReportDownload.model";
import { LongRunningTaskTypeEnum } from "../../../framework/lrtm/lrtm.service";
import { UtilsService } from "../../../shared/services/utils.service";
import { ResearchState } from "../research.service";

export enum AccountFeature {
    CompanySearch = 1,
    ScreeningToolBusinessOverview = 2,
    ScreeningToolFinancialMetrics = 3,
    ScreeningToolRatings = 4,
    ScreeningToolEnvironment = 5,
    ScreeningToolSocial = 6,
    ScreeningToolGovernance = 7,
    ScreeningToolESGEvents = 8,
    ProductInvolvement = 9,
    GlobalCompactNonCompliant = 10,
    GlobalCompactWatchlist = 11,
    GlobalCompactWatchlistAndNonCompliant = 12,
    EsgRatingsOnlineReport = 13,
    Controversies = 14,
    Governance = 15
}

/**
 * Company main service
 *
 * Author: Sorin Spiru
 * Date: 13.01.2018
 */
@Injectable()
export class CompanyService extends BaseHttpService {
    //company data observable
    public companySubject = new ReplaySubject<CompanyModel>(1);
    public company = this.companySubject.asObservable();

    //company header observable (behavior changes for each research product)
    private headerSubject = new BehaviorSubject<CompanyHeaderModel>(undefined);
    public header: Observable<CompanyHeaderModel> = this.headerSubject.asObservable();

    //company menu subject
    public menuItems = new ReplaySubject<Routes>(1);

    constructor(public http: HttpClient) {
        super();
    }

    /**
    * Get company by unique identifier
    * @param id Company unique identifier
    */
    public getCompany(id: string): void {
        let userInfo = StorageService.get().userInfo;
        let params: HttpParams = new HttpParams();
        params = params.set("userId", userInfo.userId)
            .set("accountId", userInfo.accountId)
            .set("exactMatch", 'true')
            .set("byFriendlyName", 'true')
            .set("includeFullData", 'true');

        //httpClient has issues with encoding special characters as parameters. That is why I set it into the url
        this.http.get<CompanyModel>(this.serverUrl + 'companyserv/api/v1/companies?term=' + encodeURIComponent(id), { params: params }).subscribe(data => {
            this.companySubject.next(data);
        });
    }

    /**
     * Set the company header funcional data. If undefined, the header allows user just to add the company to portfolio
     * @param data Header functional data
     */
    public setHeaderData(data: CompanyHeaderModel) {
        this.headerSubject.next(data);
    }

    public enableMenuRoutes(routes: Route[], company: CompanyModel): Route[] {
        routes.forEach(route => {
            if (route.data) {
                route.data.enabled = (route.data.featureField == undefined || company[route.data.featureField] == true) //check subscription
                    && route.data.showAsMenu === true && //is a navigation item
                    RouteGuard.canActivate(route.data.claim); //check claim
                route.data.available = this.getMenuOptionAvailability(route.path, company);
            }
        });
        return routes;
    }

    public getEsgDownloadData(company: CompanyModel) {
        return new CompanyReportDownloadModel(
            LongRunningTaskTypeEnum.ESGCompanyReportPDF, 'ESGRating',
            {
                accountId: StorageService.get().userInfo.accountId,
                accountTier: StorageService.get().userInfo.accountTier,
                companyId: company.id
            }
        );
    }

    public getRiskRatingDownloadData(company: CompanyModel) {
        return new CompanyReportDownloadModel(
            LongRunningTaskTypeEnum.RiskRatingsReport, 'RiskRating',
            {
                companyId: company.id
            }
        );
    }

    public getControversyDownloadData(company: CompanyModel) {
        return new CompanyReportDownloadModel(
            LongRunningTaskTypeEnum.ControversyReportPDF,
            'ControversyReport',
            "'" + company.id + "'"
        );
    }

    public getGovernanceDownloadData(company: CompanyModel) {
        return new CompanyReportDownloadModel(
            LongRunningTaskTypeEnum.CorporateGovernancePDF,
            'CorporateGovernance',
            {
                fileId: company.id,
                fileName: UtilsService.getCompanyReportName(company, 'CorporateGovernance'),
                fileType: 'report'
            }
        );
    }

    public getProductInvolvementDownloadData(company: CompanyModel) {
        return new CompanyReportDownloadModel(
            LongRunningTaskTypeEnum.PiReportPdf, 'ProductInvolvement',
            {
                companyId: company.id,
                companyName: company.companyName
            }
        );
    }

    public getMenuOptionAvailability(path: string, company: CompanyModel): boolean {
        // TODO: come up with a cleaner solution
        switch (path) {
            case 'risk':
                return company.riskRatingResearchState === ResearchState.ResearchAvailable || company.coreRiskResearchState === ResearchState.ResearchAvailable;
            case 'esg':
                return company.comprehensiveEsgResearchState === ResearchState.ResearchAvailable || company.coreEsgResearchState === ResearchState.ResearchAvailable;
            case 'governance':
                return company.corporateGovernanceResearchState === ResearchState.ResearchAvailable;
            case 'controversies':
                return company.controversyResearchState === ResearchState.ResearchAvailable;
            case 'globalcompact':
                return company.gccsResearchState === ResearchState.ResearchAvailable;
            case 'productInvolvement':
                return company.productInvolvementResearchState === ResearchState.ResearchAvailable;
        }

        return true;
    }
}
